import { BadRequestException, ConflictException, HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Like, Repository } from 'typeorm'
import { formatDate } from 'src/utils'
import { Permission } from './entities/permission.entity'
import { CreatePermissionDto } from './dto/create-permission.dto'
import { UpdatePermissionDto } from './dto/update-permission.dto'

@Injectable()
export class PermissionService {
  private logger = new Logger()

  @InjectRepository(Permission)
  private repository: Repository<Permission>

  async find(pageNo: number, pageSize: number, name: string) {
    // 边界条件检查
    if (pageNo <= 0 || pageSize <= 0) {
      throw new BadRequestException('页码和页数最小为 1')
    }

    const skipCount = (pageNo - 1) * pageSize
    const condition: Record<string, any> = {}
    if (name) {
      condition.name = Like(`%${name}%`)
    }

    const [permissionList, totalCount] = await this.repository.findAndCount({
      skip: skipCount,
      take: pageSize,
      where: condition,
    })

    const list = permissionList.map((menu) => {
      return {
        ...menu,
        createTime: formatDate(menu.createTime),
        updateTime: formatDate(menu.updateTime),
      }
    })

    return {
      permissionList: list,
      totalCount,
    }
  }

  async create(permissionDto: CreatePermissionDto) {
    try {
      // 原子性: 事务中的所有操作要么全部成功执行，要么全部不执行。如果事务中的任何一步失败，整个事务将回滚，保证数据库状态不变。
      // 隔离性: 多个事务并发执行时，每个事务的操作对其他事务是不可见的，直到事务提交。这可以防止并发操作导致的数据不一致。
      await this.repository.manager.transaction(async (transactionalEntityManager) => {
        const room = await transactionalEntityManager.findOne(Permission, {
          where: { code: permissionDto.code },
        })

        if (room) {
          throw new BadRequestException('权限code已存在')
        }
        const createdPermission = await transactionalEntityManager.save(Permission, permissionDto)
        return createdPermission
      })
      return '创建成功'
    }
    catch (e) {
      if (e instanceof BadRequestException) {
        // 如果是 BadRequestException，直接抛出
        throw e
      }
      else {
        // 其他错误，记录日志并抛出通用的 HttpException
        this.logger.error(`错误信息: ${e.message}`, PermissionService.name)
        throw new HttpException('创建失败，请稍后再试', HttpStatus.INTERNAL_SERVER_ERROR)
      }
    }
  }

  async update(permissionDto: UpdatePermissionDto) {
    try {
      // 验证 permissionDto.id 是否有效
      if (!permissionDto.id) {
        throw new BadRequestException('无效的权限 ID')
      }
      // 检查是否存在重复的code
      if (permissionDto.code) {
        const existingPermission = await this.repository.findOneBy({ code: permissionDto.code })
        if (existingPermission && existingPermission.id !== permissionDto.id) {
          throw new ConflictException('权限名称已存在')
        }
      }

      const permission = await this.repository.findOneBy({
        id: permissionDto.id,
      })

      if (!permission) {
        throw new BadRequestException('权限不存在')
      }

      const updatePermission = Object.assign({}, permission, permissionDto)

      // 如果需要自动更新updateTime需要使用save方法，update方法不会触发更新时间
      await this.repository.save(updatePermission)

      return '更新成功'
    }
    catch (e) {
      if (e instanceof BadRequestException) {
        throw e // 如果是 BadRequestException，直接抛出
      }
      else if (e instanceof ConflictException) {
        throw e // 直接抛出 ConflictException
      }
      else {
        // 其他错误，记录日志并抛出通用的 HttpException
        this.logger.error(`错误信息: ${e.message}`, PermissionService.name)
        throw new HttpException('更新失败，请稍后再试', HttpStatus.INTERNAL_SERVER_ERROR)
      }
    }
  }

  async delete(id: number) {
    try {
      // 输入验证
      if (!id || id <= 0) {
        throw new BadRequestException('无效的id')
      }

      await this.repository.delete({ id })
      return '删除成功'
    }
    catch (e) {
      if (e instanceof BadRequestException) {
        // 如果是 BadRequestException，直接抛出
        throw e
      }
      else {
        // 其他错误，记录日志并抛出通用的 HttpException
        this.logger.error(`错误信息: ${e.message}`, PermissionService.name)
        throw new HttpException('删除失败，请稍后再试', HttpStatus.INTERNAL_SERVER_ERROR)
      }
    }
  }
}
